package org.ocelot.tunes4j.gui;

import java.awt.Component;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.util.Arrays;
import java.util.EventObject;
import java.util.List;

import javax.swing.AbstractCellEditor;
import javax.swing.DropMode;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.RowSorter;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

import org.ocelot.tunes4j.beans.AudioObject;
import org.ocelot.tunes4j.service.AudioObjectService;
import org.ocelot.tunes4j.taggers.RegistryTagger;
import org.ocelot.tunes4j.taggers.Tagger;

import com.explodingpixels.macwidgets.MacWidgetFactory;
import com.explodingpixels.widgets.TableUtils;
import com.explodingpixels.widgets.TableUtils.SortDirection;

public class MediaTable {

	private BeanTableModel<AudioObject> model = null;
	private JTable table = null;
	private ProgressLoadDialog dialog;
	private WindowSample parentFrame;
	protected int prevRow=-1;
	protected int currentRow;
	private RowSorter<TableModel> sorter;
	
	private AudioObjectService audioService = new AudioObjectService();
	
	public MediaTable(WindowSample frame) {
		this.parentFrame = frame;
	}

	public RowSorter<TableModel> getSorter() {
		return sorter;
	}
	
	public JTable getTable() {
		return table;
	}
	
	public JScrollPane getTablePane() {

		model = new BeanTableModel<AudioObject>(AudioObject.class);
		table = MacWidgetFactory.createITunesTable(model);
		table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		table.setDropMode(DropMode.INSERT_ROWS);
		table.setDragEnabled(true);
		table.setFillsViewportHeight(true);
		table.setTransferHandler(new FileTransferHandler(parentFrame, table, audioService));
		table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		new TableColumnResizer(table);
		reorderColumnsInTable(HeaderConstants.HEADER_NAMES, table);
		configureSort(model);
		configureTableListeners();
		loadData();
		// ((DefaultCellEditor)table.getDefaultEditor(String.class)).setClickCountToStart(2);
		table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
		// //For Single Click Editing
		table.setDefaultEditor(Object.class, new MyTableCellEditor(this));
		JScrollPane scrollPane = new JScrollPane(table);
		//IAppWidgetFactory.makeIAppScrollPane(scrollPane);
		return scrollPane;
	}

	private void loadData() {
		List<AudioObject> list  = audioService.load();
        for (Object row : list) {
        	AudioObject bean = (AudioObject) row;
        	model.addRow(bean);
        }
	}

	public ProgressLoadDialog showDialog(List<File> list) {
		dialog = new ProgressLoadDialog("org.ocelot.tunes4j.taggers.JID3TaggerImpl", list, table,
				parentFrame, "Progress Dialog", true, audioService);
		return dialog;
	}
	
	public void removeSelectedItems(){
		int[] selectedRows = table.getSelectedRows();
		if(selectedRows!=null && selectedRows.length > 0) {
			int[] selectedModelRows = new int[selectedRows.length];
			int j=0;
			for(int i=0;i<selectedRows.length;i++) {
				int modelRow = table.convertRowIndexToModel(selectedRows[i]);
				selectedModelRows[j] = modelRow;
				j++;
			}
			Arrays.sort(selectedModelRows);
			model.removeRows(selectedModelRows);
		}
	}
	
	public BeanTableModel<?> getModel() {
		return model;
	}
	
	public void configureSort(BeanTableModel<AudioObject> model) {
		sorter = new TableRowSorter<TableModel>(model);
		table.setRowSorter(sorter);
		TableUtils.SortDelegate sortDelegate = new TableUtils.SortDelegate(){
			@Override
			public void sort(int arg0, SortDirection arg1) { }
		};
		TableUtils.makeSortable(table, sortDelegate);
	}

//	public void configureSort(BeanTableModel model) {
//		RowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
//	    table.setRowSorter(sorter);
//	}
	
	public void configureTableListeners() {

		final JPopupMenu popupMenu = new JPopupMenu();
		final String[] headers = HeaderConstants.HEADER_NAMES;
		for (String itemName : headers) {
			final JMenuItem item = new JCheckBoxMenuItem(itemName);
			item.setSelected(true);
			item.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent event) {
					TableColumn column = getColumnByHeaderName(item.getText());
					setColumnVisible(column, item.isSelected());
				}
			});

			popupMenu.add(item);

		}
		popupMenu.add(new JSeparator());
		addToggleVisibilityMenuItem(popupMenu, "Select All", true);
		addToggleVisibilityMenuItem(popupMenu, "Clear All", false);

		table.getTableHeader().addMouseListener(new TableHeaderMouseListener(table,sorter, popupMenu));

		table.addMouseListener(new MouseAdapter() {

			@Override
			public void mousePressed(MouseEvent e) {
				JTable table = (JTable) e.getSource();
				Point p = e.getPoint();
				int rowAtPoint = table.rowAtPoint(p);
				// Fix the sort order issue
				if(rowAtPoint < 0) return;
				int row = table.convertRowIndexToModel(rowAtPoint);
				if (table.isRowSelected(rowAtPoint)) {
					if (table.isEditing()) {        
						table.getCellEditor().stopCellEditing();
					}
					if (e.getClickCount() == 1) {
						prevRow = currentRow;
						currentRow = rowAtPoint;
					}
					if (e.getClickCount() == 2 && rowAtPoint > -1) {
						// int row = table.convertRowIndexToModel(rowAtPoint);
						if (row > -1) {
							AudioObject bean = (AudioObject) model.getRow(row);
							String filePath = bean.getPath() + File.separator
									+ bean.getFileName();
							parentFrame.getPlayer().open(new File(filePath));
							parentFrame.getPlayer().playback();
						}
					}
				}

			}
		});
		table.getModel().addTableModelListener(new MyTableModelListener(table));
	}

	public void addToggleVisibilityMenuItem(final JPopupMenu popupMenu,
			String label, final boolean visibility) {
		JMenuItem itemSelectAll = new JMenuItem(label);
		itemSelectAll.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent event) {
				for (int i = 0; i < popupMenu.getComponents().length; i++) {
					Object item = popupMenu.getComponent(i);
					if (item instanceof JCheckBoxMenuItem) {
						JCheckBoxMenuItem checkItem = (JCheckBoxMenuItem) item;
						checkItem.setSelected(visibility);
						setColumnVisible(getColumnByHeaderName(checkItem
								.getText()), visibility);
					}
				}
			}
		});
		popupMenu.add(itemSelectAll);
	}

	public void setColumnVisible(TableColumn column, boolean visible) {
		if (!visible) {
			column.setMinWidth(0);
			column.setMaxWidth(0);
		} else {
			column.setMinWidth(15);
			column.setMaxWidth(2147483647);
			column.setWidth(75);
			column.setPreferredWidth(75);
		}

	}

	public TableColumn getColumnByHeaderName(String headerName) {
		int selectedIndex = -1;
		TableColumn selectedColumn = null;
		for (int i = 0; i < model.getColumnCount(); i++) {
			if (headerName.equals(table.getColumnModel().getColumn(i)
					.getHeaderValue())) {
				selectedIndex = i;
			}
		}
		if (selectedIndex > -1) {
			selectedColumn = table.getColumnModel().getColumn(selectedIndex);
		}
		return selectedColumn;
	}

	public static void reorderColumnsInTable(final String[] order,
			final JTable table) {
		TableColumnModel model = table.getColumnModel();
		for (int newIndex = 0; newIndex < order.length; newIndex++) {
			String columnName = order[newIndex];
			int index = model.getColumnIndex(columnName);
			if (index != newIndex) {
				model.moveColumn(index, newIndex);
			}
		}
	}

	public class MyTableModelListener implements TableModelListener {

		private static final long serialVersionUID = 1L;

		JTable table;

		MyTableModelListener(JTable table) {
			this.table = table;
		}

		public void tableChanged(TableModelEvent e) {
			int firstRow = e.getFirstRow();
			int lastRow = e.getLastRow();
			switch (e.getType()) {
				case TableModelEvent.UPDATE:
					if (!(firstRow == TableModelEvent.HEADER_ROW)) {
						for (int r = firstRow; r <= lastRow; r++) {
							AudioObject bean = (AudioObject) model.getRow(r);
							System.out.println("Changed bean:" + bean);
							RegistryTagger registry = new RegistryTagger();
							Tagger tagger = registry.getInsance("org.ocelot.tunes4j.taggers.JID3TaggerImpl");
							String filePath = bean.getPath() + File.separator + bean.getFileName();
							tagger.save(new File(filePath), bean);
							audioService.save(bean);
							System.out.println("file saved!!!");
						}
					}
				case TableModelEvent.DELETE:
						AudioObject bean = (AudioObject) model.getRow(firstRow);
						audioService.remove(bean);
				break;
			}
		}
	}

	public class MyTableCellEditor extends AbstractCellEditor implements
			TableCellEditor {
		private static final long serialVersionUID = 1L;
		private JComponent component = null;
		private MediaTable media;

		public MyTableCellEditor(MediaTable media) {
			super();
			this.media = media;
		}

		@Override
		public Component getTableCellEditorComponent(JTable table,
				Object value, boolean isSelected, int row, int column) {
			component = new JTextField();
			((JTextField) component).setText((String) value);
			return component;
		}

		@Override
		public Object getCellEditorValue() {
			return ((JTextField) component).getText();
		}

		@Override
		public boolean isCellEditable(EventObject evt) {
			if (media.prevRow == media.currentRow) {
				return true;
			}
			return false;
		}
		

	}

}
